﻿#ifndef PULLSTREAM_H
#define PULLSTREAM_H

#include <QObject>
#include <QThread>

#ifdef _WIN32
//Windows
extern "C"
{
#include <libavformat/avformat.h>
#include <libavutil/mathematics.h>
#include <libavutil/time.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavformat/avformat.h>
#include <libavutil/mathematics.h>
#include <libavutil/time.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#ifdef __cplusplus
};
#endif
#endif

/**
 * @brief 从rtmp服务器拉取视频流
 */
class PullStream : public QThread
{
    Q_OBJECT
public:
    explicit PullStream(QObject *parent = nullptr);

private:
    /**
     * @brief initConfig 初始化配置
     */
    void initConfig();

    /**
     * @brief freeMemory 释放ffmpeg对象的内存
     */
    void freeMemory();


    /**
     * @brief parserFlvSEI 解析FLV格式中的SEI数据
     * @param packet AVPacket
     */
    void parserFlvSEI(const AVPacket* const packet);
protected:
    void run() override;

public:
    /**
     * @brief init 初始化ffmpeg
     * @return
     */
    bool init();

signals:
    /**
     * @brief emitImage 向主界面发送显示的图片
     * @param image 图片
     */
    void emitImage(const QImage& image);

    /**
     * @brief emitUuidSEI 发送解析出来的UUID 和 SEI数据
     * @param uuid      uuid
     * @param sei_data  sei数据
     */
    void emitUuidSEI(const QByteArray& uuid, const QByteArray& sei_data);

private:
    /**
     * @brief pFormatCtx 拉流的格式上下文
     */
    AVFormatContext *pFormatCtx;
    /**
     * @brief pCodecCtx 编解码器上下文
     */
    AVCodecContext *pCodecCtx;
    /**
     * @brief pCodec 编解码器
     */
    AVCodec *pCodec;
    /**
     * @brief pFrame 图片Frame
     */
    AVFrame *pFrame, *pFrameRGB;
    /**
     * @brief pPacket
     */
    AVPacket *pPacket;
    /**
     * @brief buffer
     */
    uint8_t *buffer;
    /**
     * @brief sws_ctx 图片转换
     */
    struct SwsContext *sws_ctx;

    int videoStream;

    /**
     * @brief rtmpAddr 拉流地址
     */
    QString rtmpAddr;

    /**
     * @brief bInit 是否初始化成功
     */
    bool bInit;
};

#endif // PULLSTREAM_H
